package com.easybuilder.core.im.controller;

import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@ServerEndpoint("/ws/video")
public class WsVideoController {

    //region 用来解决mapper注入失败问题
    /**
     * 说明：
     * 本质原因：spring管理的都是单例（singleton），和 websocket （多对象）相冲突。
     * 详细解释：项目启动时初始化，会初始化 websocket （非用户连接的），spring 同时会为其注入 service，该对象的 service 不是 null，被成功注入。但是，由于 spring 默认管理的是单例，所以只会注入一次 service。
     * 当新用户进入聊天时，系统又会创建一个新的 websocket 对象，这时矛盾出现了：spring 管理的都是单例，不会给第二个 websocket 对象注入 service，所以导致只要是用户连接创建的 websocket 对象，都不能再注入了。
     *
     * 像 controller 里面有 service， service 里面有 dao。因为 controller，service ，dao 都有是单例，所以注入时不会报 null。但是 websocket 不是单例，所以使用spring注入一次后，后面的对象就不会再注入了，会报null。
     */
    private static ApplicationContext applicationContext;

    public static void setApplicationContext(ApplicationContext applicationContext){
        WsVideoController.applicationContext = applicationContext;
    }
    //endregion

    private static AtomicInteger onlineCount = new AtomicInteger(0); //在线连接数量
    public static volatile ConcurrentHashMap<String, Session> container = new ConcurrentHashMap<>(); //存放有效连接


    //region 连接成功回调
    @OnOpen
    public void onOPen(Session session) {
        int count = onlineCount.incrementAndGet(); //在线连接数量 + 1
        container.put(session.getId(), session);
        System.out.println("在线连接数量+1：" + count);

    }
    //endregion

    //region 关闭连接回调
    @OnClose
    public void onClose(Session session) throws IOException {
        int count = onlineCount.decrementAndGet();
        removeSession(session);
        System.out.println("在线连接数量-1：" + count);
    }
    //endregion

    //region 收到消息
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        System.out.println("wsVideo收到消息：" + message);
    }
    //endregion

    //region 错误回调
    @OnError
    public void onError(Session session, Throwable err) {
        System.out.println("出现错误！" + err.getMessage());
    }
    //endregion

    //region 推送消息
    public static void sendMsg(String msg, Session toSession) throws IOException {
        toSession.getBasicRemote().sendText(msg);

    }
    //endregion

    //region 移除session 及计划编号中所对应的 sessionId
    private void removeSession(Session session) throws IOException {
        container.remove(session.getId()); //移除session
    }
    //endregion

}
